package com.audaque.springboot.foshanupload.web.datamongodbdemo.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.audaque.springboot.foshanupload.web.datamongodbdemo.api.MusicControllerApi;
import com.audaque.springboot.foshanupload.web.datamongodbmodeldemo.model.pojo.Book;
import com.audaque.springboot.foshanupload.web.datamongodbmodeldemo.model.pojo.Chapter;
import com.audaque.springboot.foshanupload.web.datamongodbmodeldemo.model.pojo.MusicDetail;
import com.audaque.springboot.foshanupload.web.datamongodbmodeldemo.model.qo.MusicQo;
import com.mongodb.client.*;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import com.mongodb.client.result.InsertOneResult;
import org.apache.commons.lang3.StringUtils;
import org.bson.BsonObjectId;
import org.bson.BsonValue;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.json.JsonMode;
import org.bson.json.JsonWriterSettings;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author zgb
 * @desc 与原生语法对应, 操作Bson,使用Bson的api：Bson
 * @date 2023-07-21 18:48:38
 */
@RestController
@RequestMapping("/musicDetailMongoClient")
public class MusicDetailMongoClientController implements MusicControllerApi {

    @Autowired
    private MongoDatabase mongoDatabase;
    private MongoCollection<Document> collection;

    @PostConstruct
    public void init() {
        //获取集合
        collection = mongoDatabase.getCollection("music_detail");
        if (collection == null) {
            mongoDatabase.createCollection("music_detail");
            System.out.println("集合创建成功");
            //获取集合
            collection = mongoDatabase.getCollection("music_detail");
        }


    }


    @GetMapping("/test")
    public void test() {
        //向集合中插入文档
        Document document = new Document("name", "管理员").
                append("code", "manager").
                append("sort", 100);
        List<Document> documents = new ArrayList<>();
        documents.add(document);
        collection.insertMany(documents);
        System.out.println("文档插入成功");

        //更新文档
        collection.updateMany(Filters.eq("code", "manager"), new Document("$set", new Document("name", "经理")));


        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //遍历所有文档
        FindIterable<Document> findIterable = collection.find();
        MongoCursor<Document> mongoCursor = findIterable.iterator();
        while (mongoCursor.hasNext()) {
            System.out.println(mongoCursor.next());
        }

        //查询当前集合所有文档数量
        long count = collection.countDocuments();
        System.out.println("当前文档数量:" + count);

        //带条件遍历文档
        FindIterable<Document> documentFindIterable = collection.find(Filters.eq("code", "manager"));
        MongoCursor<Document> documentMongoCursor = documentFindIterable.iterator();
        while (documentMongoCursor.hasNext()) {
            System.out.println(documentMongoCursor.next());
        }


        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        //删除符合条件的第一个文档
        collection.deleteOne(Filters.eq("code", "manager"));
        //删除所有符合条件的文档
        collection.deleteMany(Filters.eq("code", "manager"));


        collection.drop();
        System.out.println("集合 tb_role 删除成功");


    }

    @Override
    @PostMapping("/add")
    public String add(@RequestBody MusicDetail musicDetail) {
        //添加id
        musicDetail.setId(new ObjectId().toString());
        Book book = musicDetail.getBook();
        book.setId(new ObjectId().toString());
        Chapter chapter = book.getChapter();
        chapter.setId(new ObjectId().toString());
        String s1 = JSONUtil.toJsonStr(musicDetail);
        Document document =  Document.parse(s1);
        InsertOneResult insertOneResult = collection.insertOne(document);
        BsonValue insertedId = insertOneResult.getInsertedId();
        BsonObjectId bsonObjectId = insertedId.asObjectId();
        ObjectId value = bsonObjectId.getValue();
        String s = value.toString();
        return s;
    }

    /**
     * 更新：部分更新，但不支持嵌套
     * @param musicDetail
     * @throws Exception
     */
    @Override
    @PutMapping("/edit")
    public void edit(@RequestBody MusicDetail musicDetail) throws Exception {
        String _id = musicDetail.get_id();

        if (StringUtils.isBlank(_id)) {
            throw new Exception("_id不能为null");
        }
        FindIterable<Document> one = collection.find(Filters.eq("_id", _id));
        Document first = one.first();
        if (first==null) {
            throw new Exception("根据id查不到该记录");
        }



        JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED)
                .objectIdConverter((value, writer) -> writer.writeString(value.toHexString()))
                .dateTimeConverter(
                        (value, writer) -> {
                            ZonedDateTime zonedDateTime = Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC);
                            writer.writeString(DateTimeFormatter.ISO_DATE_TIME.format(zonedDateTime));
                        })
                .build();


        String json = first.toJson(settings);
        MusicDetail byId = JSONUtil.toBean(json, MusicDetail.class);

        CopyOptions copyOptions = CopyOptions.create();
        copyOptions.setIgnoreNullValue(true);
        copyOptions.setIgnoreProperties("book");
        BeanUtil.copyProperties(musicDetail,byId,copyOptions);

        Book book = musicDetail.getBook();
        Book book1 = byId.getBook();
        copyOptions.setIgnoreProperties("chapter");
        BeanUtil.copyProperties(book,book1,copyOptions);

        Chapter chapter = book.getChapter();
        Chapter chapter1 = book1.getChapter();
        BeanUtil.copyProperties(chapter,chapter1,copyOptions);
        book1.setChapter(chapter1);
        byId.setBook(book1);


        byId.set_id(null);
        JSONConfig jsonConfig = JSONConfig.create();
        jsonConfig.setIgnoreNullValue(true);
        jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        String s = JSONUtil.toJsonStr(byId,jsonConfig);
        Document document = Document.parse(s);


        collection.updateOne(Filters.eq("_id", _id), new Document("$set", document));

    }

    @Override
    public void editField(String id, String name) throws Exception {

    }

    @Override
    @PutMapping("/override2json")
    public void override2json(@RequestParam  String _id) throws Exception {


        if (StringUtils.isBlank(_id)) {
            throw new Exception("_id不能为null");
        }
        ObjectId objectId = new ObjectId(_id);
        FindIterable<Document> one = collection.find(Filters.eq("_id", objectId));
        Document first = one.first();
        if (first==null) {
            throw new Exception("根据id查不到该记录");
        }



        JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED)
                .objectIdConverter((value, writer) -> writer.writeString(value.toHexString()))
                .dateTimeConverter(
                        (value, writer) -> {
                            ZonedDateTime zonedDateTime = Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC);
                            writer.writeString(DateTimeFormatter.ISO_DATE_TIME.format(zonedDateTime));
                        })
                .build();


        String json = first.toJson(settings);
        MusicDetail byId = JSONUtil.toBean(json, MusicDetail.class);
        byId.set_id(null);
        JSONConfig jsonConfig = JSONConfig.create();
        jsonConfig.setIgnoreNullValue(true);
        jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        String s = JSONUtil.toJsonStr(byId,jsonConfig);
        Document document = Document.parse(s);


        collection.updateOne(Filters.eq("_id", objectId), new Document("$set", document));

    }

    @Override
    @PutMapping("/override")
    public void override(@RequestBody  MusicDetail musicDetail) throws Exception {
        String _id = musicDetail.get_id();

        if (StringUtils.isBlank(_id)) {
            throw new Exception("_id不能为null");
        }
        ObjectId objectId = new ObjectId(_id);
        musicDetail.set_id(null);
        String s1 = JSONUtil.toJsonStr(musicDetail);
        Document document =  Document.parse(s1);

        collection.replaceOne(Filters.eq("_id", objectId), document);
    }

    @Override
    @GetMapping("/get/{id}")
    public MusicDetail get(@PathVariable("id") String _id) {
        ObjectId objectId = new ObjectId(_id);
        FindIterable<Document> one = collection.find(Filters.eq("_id", objectId));
        Document first = one.first();


        JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED)
                .objectIdConverter((value, writer) -> writer.writeString(value.toHexString()))
                .dateTimeConverter(
                        (value, writer) -> {
                            ZonedDateTime zonedDateTime = Instant.ofEpochMilli(value).atZone(ZoneOffset.UTC);
                            writer.writeString(DateTimeFormatter.ISO_DATE_TIME.format(zonedDateTime));
                        })
                .build();


        String json = first.toJson(settings);
        MusicDetail musicDetail = JSONUtil.toBean(json, MusicDetail.class);
        return musicDetail;

    }

    @Override
    public void del(String id) {

    }

    @Override
    public Page<MusicDetail> page(int page, int size, MusicQo musicQo) {
        return null;
    }

    @Override
    public MusicDetail dBRef(String bookId) {
        return null;
    }


    @GetMapping("/aggregate")
    public  AggregateIterable<Document> aggregate( ) {
        Bson filter = null;
        AggregateIterable<Document> aggregate = collection.aggregate(Arrays.asList(
                Aggregates.match(filter),
                Aggregates.group("$musicType", Accumulators.sum("id", "$id")),
                Aggregates.sort(Sorts.descending("musicType"))));
        return aggregate;
    }






}
